import {_decorator, Component, Node, Prefab, Vec3} from 'cc';
import {BaseInfo} from "db://assets/scripts/data/model/BaseInfo";
import {AudioManager} from "db://assets/scripts/common/AudioManager";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {EffectManager} from "db://assets/scripts/common/EffectManager";
import {Skill} from "db://assets/scripts/data/model/Skill";
import {AudioPaths} from "db://assets/scripts/common/AudioPaths";
import {WarningCircleEffect} from "db://assets/scripts/game/effect/warningSkill/WarningCircleEffect";
import {WarningLineEffect} from "db://assets/scripts/game/effect/warningSkill/WarningLineEffect";
import {MonsterController} from "db://assets/scripts/game/role/monster/MonsterController";
import {WarningStripEffect} from "db://assets/scripts/game/effect/warningSkill/WarningStripEffect";
import {GameState} from "db://assets/scripts/game/GameState";

const {ccclass, property} = _decorator;

/**
 * 小火球脚本：抛物线，只有落地(播放爆炸)才有伤害, 所以碰撞器在hitFireBall1里面
 */
@ccclass('FireBallEffect')
export class FireBallEffect extends Component {
    /**
     * 是否播放火球
     */
    public isPlayHitFireBall: boolean = false;
    /**
     * 地面相对世界原点高度
     */
    public groundWorldPositionY: number = 1.8;
    /**
     * 预警技能脚本
     */
    public warningScript: WarningCircleEffect | WarningLineEffect | WarningStripEffect;
    /**
     * 技能信息
     */
    public skill: Skill;
    /**
     * 敌人基本信息
     */
    public baseInfo: BaseInfo;

    /**
     * 方向是否自动调整
     */
    private isAutoRotate: boolean = true;
    /**
     * 开始位置
     */
    private startPosition: Vec3 = new Vec3();
    /**
     * 结束位置
     */
    private endPosition: Vec3 = new Vec3();
    /**
     * 开始和结束位置差
     */
    private offsetPosition: Vec3 = new Vec3();
    /**
     * 小火球飞行时间
     */
    private totalFlyTime: number = 0;
    /**
     * 小火球最大飞行高度
     */
    private flyMaxHeight: number = 0;
    /**
     * 当前飞行时间
     */
    private currentFlyTime: number = 0;
    /**
     * 每隔0.1秒调整角度
     */
    private rotateCoolTime: number = 0;
    /**
     * 下次的目标位置
     */
    private nextTargetPosition: Vec3 = new Vec3();
    /**
     * 关联的怪物脚本
     */
    private parentScript: MonsterController;
    /**
     * 目标位置
     */
    private targetPos: Vec3 = new Vec3();

    /**
     * 初始化
     *
     * @param skill 技能信息
     * @param baseInfo 基础信息
     * @param parentScript 使用者
     */
    public init(skill: Skill, baseInfo: BaseInfo, parentScript?: MonsterController) {
        this.skill = skill;
        this.baseInfo = baseInfo;
        this.parentScript = parentScript;
        this.totalFlyTime = 0;
        this.flyMaxHeight = 0;
        this.currentFlyTime = 0;
        this.startPosition.set(this.node.worldPosition.x, this.groundWorldPositionY, this.node.worldPosition.z);
        this.endPosition.set(parentScript.attackPosition);
        Vec3.subtract(this.offsetPosition, this.endPosition, this.startPosition);
        this.totalFlyTime = this.offsetPosition.length() / skill.speed;
        // 最大飞行高度跟飞行距离成正比
        this.flyMaxHeight = this.totalFlyTime * 3;
        this.isPlayHitFireBall = false;

        this.node.children.forEach((ndChild: Node) => {
            ndChild.active = true;
        })

        EffectManager.getInstance().playParticle(this.node);

        AudioManager.getInstance().playSound(AudioPaths.fireBallSound);
    }

    update(deltaTime: number) {
        if (!this.node.parent
            || !GameManager.getInstance().gamePlayerProxy.getPlayerNode()
            || GameManager.getInstance().gameStateProxy.getGameState() === GameState.OVER
            || GameManager.getInstance().gameStateProxy.getGameState() === GameState.PAUSE) {
            return;
        }

        // 向指定目标飞行
        if (this.totalFlyTime > 0 && this.node.parent) {
            if (this.currentFlyTime < this.totalFlyTime) {
                this.currentFlyTime += deltaTime;
                this.currentFlyTime = this.currentFlyTime >= this.totalFlyTime ? this.totalFlyTime : this.currentFlyTime;

                let percent = Number((this.currentFlyTime / this.totalFlyTime).toFixed(2));
                // 曲线飞行
                let height = this.flyMaxHeight * Math.cos(percent * Math.PI - Math.PI / 2);
                this.targetPos.set(this.startPosition.x + this.offsetPosition.x * percent, this.startPosition.y + height, this.startPosition.z + this.offsetPosition.z * percent);

                this.node.setWorldPosition(this.targetPos);

                if (this.isAutoRotate) {
                    this.rotateCoolTime -= deltaTime;
                    if (this.rotateCoolTime < 0) {
                        this.rotateCoolTime = 0.1;
                        percent = Number(((this.currentFlyTime + deltaTime) / this.totalFlyTime).toFixed(2));
                        if (percent < 1) {
                            // 曲线飞行
                            height = this.flyMaxHeight * Math.cos(percent * Math.PI - Math.PI / 2);
                            this.nextTargetPosition.set(this.startPosition.x + this.offsetPosition.x * percent, this.startPosition.y + height, this.startPosition.z + this.offsetPosition.z * percent)
                            this.node.forward = this.nextTargetPosition.subtract(this.targetPos).normalize();
                        }
                    }
                }

                // 小火球碰到地面
                if (Number((this.node.position.y).toFixed(2)) <= this.groundWorldPositionY && !this.isPlayHitFireBall && this.currentFlyTime > 0) {
                    this.isPlayHitFireBall = true;

                    // 关闭预警
                    this.parentScript.warningScript?.hideWarning();

                    this.node.children.forEach((child: Node) => {
                        child.active = false;
                    })

                    // 展示火焰爆炸
                    ResourceUtils.loadEffect("hit/hitFireBall1").then((prefab: Prefab) => {
                        let ndEffect: Node = PoolManager.getInstance().getNode(prefab, this.node);
                        ndEffect.setWorldPosition(this.node.worldPosition);

                        EffectManager.getInstance().playParticle(ndEffect,
                            GameManager.getInstance().gameSpeedProxy.getGameSpeed(),
                            true, 1.1, () => {
                            PoolManager.getInstance().putNode(this.node);
                        });
                    })
                }
            }
        }
    }
}